﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using Elmah;
using System.Web.Mvc;
using Site.Infrastructure.Logging;

namespace WikiGame.Infrastructure.ErrorHandling
{
    public class ElmahErrorHandler : HandleErrorAttribute
    {
        private ILogger logger;

        public ElmahErrorHandler(ILogger logger_)
        {
            logger = logger_;
        }

        public override void OnException(ExceptionContext context)
        {
            base.OnException(context);

            var e = context.Exception;

            if (!context.ExceptionHandled   // if unhandled, will be logged anyhow
                || RaiseErrorSignal(e)      // prefer signaling, if possible
                || IsFiltered(context))     // filtered?
                return;

            LogException(e);
        }

        private bool RaiseErrorSignal(Exception e)
        {
            var context = HttpContext.Current;
            if (context == null)
                return false;
            var signal = ErrorSignal.FromContext(context);
            if (signal == null)
                return false;
            signal.Raise(e, context);
            return true;
        }

        private bool IsFiltered(ExceptionContext context)
        {
            var config = context.HttpContext.GetSection("elmah/errorFilter")
                         as ErrorFilterConfiguration;

            if (config == null)
                return false;

            var testContext = new ErrorFilterModule.AssertionHelperContext(
                                      context.Exception, HttpContext.Current);

            return config.Assertion.Test(testContext);
        }

        private void LogException(Exception e)
        {
            var context = HttpContext.Current;
            Elmah.ErrorLog.GetDefault(context).Log(new Error(e, context));
            logger.Error(e);
        }
    }
}
